﻿using HenuAlbum.ControllerModels;
using HenuAlbum.DbContext;
using HenuAlbum.Identity;
using HenuAlbum.Models;
using HenuAlbum.ResponseModels;
using HenuAlbum.Utils;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace HenuAlbum.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class AlbumController : ControllerBase
    {

        private readonly AppDbContext _appDbContext;

        private readonly UserManager<User> _userManager;

        public AlbumController(AppDbContext appDbContext, UserManager<User> userManager)
        {
            _appDbContext = appDbContext;
            _userManager = userManager;
        }

        [HttpGet("Query")]
        public async Task<IActionResult> Query(int? collegeId, int? majorId, int? classId, int? gradeId, int limit = 20, int page = 1)
        {
            Tools.ResolveLimitAndPage(ref limit, ref page, 20, 100);

            var list = await _appDbContext.ClassAlbumView
                .AsNoTracking()
                .Where(x => 
                    (x.IsPublic) && 
                    (x.ReviewState == null || x.ReviewState == ReviewState.Reviewed) &&
                    (collegeId == null ? true : x.CollegeId == collegeId) &&
                    (majorId == null ? true : x.MajorId == majorId) &&
                    (classId == null ? true : x.ClassId == classId) &&
                    (gradeId == null ? true : x.GradeId == gradeId))
                .OrderBy(x => x.AlbumId)
                .Skip(limit * (page - 1))
                .Take(limit)
                .ToListAsync();

            return Ok(new ArrayResponse(list.Select((x) =>
            {
                var r = _appDbContext.Resources
                .Where(t => t.AlbumId == x.AlbumId)
                .Select(x => new { x.Id, x.DownloadCount })
                .FirstOrDefault();
                var likeCount =  _appDbContext.UserLikeAlbum.Count(y => y.AlbumId == x.AlbumId);
                return new
                {
                    x.AlbumId,
                    AlbumType = x.Discriminator,
                    x.ReviewState,
                    x.Title,
                    x.Description,
                    x.IsPublic,
                    x.CreatorId,
                    CoverId = r?.Id,
                    LikeCount = likeCount,
                    DownloadCount = r?.DownloadCount
                };
            }).ToList()));
        }


    [HttpPost("{albumId}/Like")]
    [Authorize]
    public async Task<IActionResult> LikeAlbum(int albumId)
    {
        var albumExists = await _appDbContext.Albums.AnyAsync(x => x.Id == albumId);
        if (!albumExists)
        {
            return BadRequest(new NotExistsError("相册不存在"));
        }
        int userId = int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier));
        var exists = await _appDbContext.UserLikeAlbum.AnyAsync(x => x.AlbumId == albumId && x.UserId == userId);
        if (exists)
        {
            return BadRequest(new AlreadyExistsError("你已经点赞!"));
        }
        _appDbContext.UserLikeAlbum.Add(new UserLikeAlbum()
        {
            AlbumId = albumId,
            UserId = userId
        });
        await _appDbContext.SaveChangesAsync();
        return Ok(new OkResponse("点赞成功!"));
    }

    [HttpPost("{albumId}/Unlike")]
    [Authorize]
    public async Task<IActionResult> UnlikeAlbum(int albumId)
    {
        int userId = int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier));
        var record = await _appDbContext.UserLikeAlbum
            .Where(x => x.AlbumId == albumId && x.UserId == userId)
            .FirstOrDefaultAsync();
        if (record == null)
        {
            return BadRequest(new AlreadyExistsError("你没有给该相册点赞!"));
        }
        _appDbContext.UserLikeAlbum.Remove(record);
        await _appDbContext.SaveChangesAsync();
        return Ok(new OkResponse("取消点赞成功!"));
    }

    [HttpGet("{albumid:int}/Comments")]
    [Authorize]
    public async Task<IActionResult> GetComments(int albumid)
    {

        var album = await _appDbContext.Albums.AsNoTracking()
                               .Where(x => x.Id == albumid)
                               .FirstOrDefaultAsync();
        if (null == album)
        {
            return BadRequest(new NotExistsError("相册不存在"));
        }
        //暂时只让管理员和访问公开相册时看到所有评论
        if (album.IsPublic || User.IsInRole("管理员"))
        {
            var comments = await _appDbContext.Comments
                .AsNoTracking()
                .Include(x => x.Album)
                .Include(y => y.Commentator)
                .Where(e => e.AlbumId == albumid && e.ReviewState == ReviewState.Reviewed)
                .Select(f => new
                {
                    Commentid = f.Id,
                    f.Content,
                    Commentator = new
                    {
                        f.CommentatorId,
                        Name = f.Commentator.UserName,
                    },

                    f.CommentTime
                })
                .ToArrayAsync();
            return Ok(new OkResponse() { Data = comments });
        }
        return BadRequest(new IncorrectError("权限不允许"));
    }

    [HttpPost("AddComment")]
    [Authorize]
    public async Task<IActionResult> AddComments(AddCommentParam param)
    {

        //查找评论所对应的相册
        var album = await _appDbContext.Albums.AsNoTracking()
                                        .Where(x => x.Id == param.AlbumId).FirstOrDefaultAsync();
        if (null == album)
        {
            return BadRequest(new NotExistsError("相册不存在"));
        }
        //如果相册不是公开的访问者又不是辅导员
        if (!album.IsPublic && User.IsInRole("管理员"))
        {
            return BadRequest(new IncorrectError("权限不允许"));
        }
        var user = await _userManager.GetUserAsync(User);
        var comment = new Comments()
        {
            CommentatorId = user.Id,
            CommentTime = System.DateTime.Now,
            Content = param.Content,
            AlbumId = album.Id,
            ReviewState = ReviewState.Unreviewed
        };
        await _appDbContext.Comments.AddAsync(comment);
        await _appDbContext.SaveChangesAsync();
        return Ok(new OkResponse()
        {
            Data = new
            {
                commentid = comment.Id,
                CommentatorId = user.Id,
                CommentatorName = user.UserName
            }
        });

    }

    [HttpPost("DeleteComment")]
    [Authorize]
    public async Task<IActionResult> DeleteComments([FromQuery] int commentId)
    {
        var comment = await _appDbContext.Comments.Include(x=>x.Album).Where(x => x.Id == commentId).FirstOrDefaultAsync();
        if (null == comment)
        {
            return BadRequest(new IncorrectError("评论不存在"));
        }
        var user = await _userManager.GetUserAsync(this.User);
        //访问者删除的评论的id不是自己的id且又不是管理员
        if (user.Id != comment.Album.CreatorId&&user.Id!=comment.CommentatorId && !User.IsInRole("管理员") && !User.IsInRole("辅导员"))
        {
            return BadRequest(new IncorrectError("权限不够"));
        }
        _appDbContext.Comments.Remove(comment);
        await _appDbContext.SaveChangesAsync();
        return Ok(new OkResponse());

    }

    [HttpGet("{albumId}/Resources")]
    public async Task<IActionResult> GetResources(int albumId)
    {
        var album = await _appDbContext.Albums.Where(x => x.Id == albumId).FirstOrDefaultAsync();
        if (album == null) return BadRequest(new NotExistsError("相册不存在"));

        //获取所有资源
        var resources = await _appDbContext.Resources
                .AsNoTracking()
                .Include(e => e.Album)
                .Include(y => y.Tags)
                .Include(z => z.Uploader)
                .Where(x => x.AlbumId == albumId)
                .Select(x => new
                {
                    ResourceId = x.Id,
                    ResourceTitle = x.Title,
                    ResourceDescription = x.Description,
                    ShootingDate = x.ShootingDate,
                    Location = x.Location,
                    UploaderId = x.Uploader.Id,
                    CreateTime = x.CreateTime,
                    ResourceType = x.Type,
                    DownloadCount = x.DownloadCount,
                    Album = new
                    {
                        AlbumId = x.Album.Id,
                        AlbumTitle = x.Album.Title,
                        AlbumDescription = x.Album.Description,
                    },
                    Tags = x.Tags.Select(t => new
                    {
                        t.Id,
                        t.ForSelection,
                        t.Name,
                        t.Description
                    })
                })
                .ToListAsync();

        if (User.IsInRole("管理员") || User.IsInRole("辅导员"))
        {
            // 这个接口管理员和辅导员都有所有权限
        }
        else
        {
            var user = await _userManager.GetUserAsync(User);
            if (user == null || user.Id != album.CreatorId)
            {
                if (album is PersonalAlbum p && p.ReviewState != ReviewState.Reviewed)
                {
                    return BadRequest(new IncorrectError("该相册未通过审核！"));
                }

                if (!album.IsPublic)
                {
                    resources = null;
                }
            }
        }

        if (resources == null)
        {
            return BadRequest(new NotExistsError("该相册是空的或无权限访问!"));
        }

        return Ok(new ArrayResponse(resources));
    }

    [HttpGet("Recently")]
    public async Task<IActionResult> GetRecentAlbum(string? type, int limit = 20)
    {
        if (limit > 20) limit = 20;
        if (limit < 0) limit = 0;
        List<Album> albums = await _appDbContext.PersonalAlbums.Where(e => e.IsPublic && e.ReviewState == ReviewState.Reviewed).Cast<Album>().ToListAsync();
        var other = await _appDbContext.Albums.Where(e => e.IsPublic && !e.Discriminator.Equals("PersonalAlbum")).ToListAsync();
        albums.AddRange(other);
        var result = albums.OrderByDescending(y => y.CreateTime).Take(limit).ToList();

        if (!string.IsNullOrEmpty(type))
        {
            result.RemoveAll(x => !x.Discriminator.Equals(type));
        }
        return Ok(new OkResponse()
        {
            Data = result.Select(x => new
            {
                x.Id,
                x.Title,
                x.Description,
                x.IsPublic,
                x.CreateTime,
                type = x.Discriminator
            })
        });


    }

    [HttpGet("Comments/Unreviewed")]
    [Authorize(Roles = "管理员, 辅导员")]
    public async Task<IActionResult> GetUnReviewedComments(int? collegeId, int? majorId, int? gradeId, int? albumid, ReviewState reviewState = ReviewState.Unreviewed, int limit = 20, int page = 1)
    {
        Tools.ResolveLimitAndPage(ref limit, ref page, 20, 100);
        var list = await _appDbContext.Comments
                .AsNoTracking()
                .Include(x => x.Album)
                .Include(x => x.Commentator)
                .ThenInclude(x => x.Class)
                .Where(x => x.ReviewState == reviewState &&
                         (albumid == null ? true : x.AlbumId == albumid) &&
                        (gradeId == null ? true : x.Commentator.Class.GradeId == gradeId) &&
                        (majorId == null ? true : x.Commentator.Class.MajorId == majorId) &&
                        (collegeId == null ? true : x.Commentator.Class.Major.CollegeId == collegeId))
                .Select(x => new
                {
                    x.Id,
                    x.AlbumId,
                    AlbumTitle = x.Album.Title,
                    AlbumDescription = x.Album.Description,
                    CommentatorId = x.Commentator.Id,
                    CommentatorName = x.Commentator.UserName,
                    CommentatorFullName = x.Commentator.FullName,
                    x.Content,
                    x.CommentTime
                })
                .OrderByDescending(x => x.CommentTime)
                .Skip(limit * (page - 1))
                .Take(limit)
                .ToListAsync();
        return Ok(new ArrayResponse(list));
    }

    [HttpPost("Comments/{commentId}/MarkReviewed")]
    [Authorize(Roles = "管理员, 辅导员")]
    public async Task<IActionResult> MarkReviewed(int commentId)
    {
        var comment = await _appDbContext.Comments
            .Where(x => x.Id == commentId)
            .FirstOrDefaultAsync();
        if (comment == null) return BadRequest(new NotExistsError("评论不存在!"));

        comment.ReviewState = ReviewState.Reviewed;
        await _appDbContext.SaveChangesAsync();
        return Ok(new OkResponse());
    }

    [HttpPost("Comments/{commentId}/MarkUnreviewed")]
    [Authorize(Roles = "管理员, 辅导员")]
    public async Task<IActionResult> MarkUnreviewed(int commentId)
    {
        var comment = await _appDbContext.Comments
            .Where(x => x.Id == commentId)
            .FirstOrDefaultAsync();
        if (comment == null) return BadRequest(new NotExistsError("评论不存在!"));

        comment.ReviewState = ReviewState.Unreviewed;
        await _appDbContext.SaveChangesAsync();
        return Ok(new OkResponse());
    }

    [HttpPost("Comments/{commentId}/MarkFailed")]
    [Authorize(Roles = "管理员, 辅导员")]
    public async Task<IActionResult> MarkFailed(int commentId)
    {
        var comment = await _appDbContext.Comments
            .Where(x => x.Id == commentId)
            .FirstOrDefaultAsync();
        if (comment == null) return BadRequest(new NotExistsError("评论不存在!"));

        comment.ReviewState = ReviewState.Failed;
        await _appDbContext.SaveChangesAsync();
        return Ok(new OkResponse());
    }

}
}
